package com.zzyl.nursing.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.QueryDevicePropertyStatusRequest;
import com.aliyun.iot20180120.models.QueryDevicePropertyStatusResponse;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.core.domain.AjaxResult;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.framework.config.properties.AliIoTConfigProperties;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.AddFamilyDto;
import com.zzyl.nursing.dto.UserLoginRequestDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.service.IDeviceDataService;
import com.zzyl.nursing.service.IDeviceService;
import com.zzyl.nursing.service.IFamilyMemberService;
import com.zzyl.nursing.service.WechatService;
import com.zzyl.nursing.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 老人家属Service业务层处理
 * 
 * @author alexis
 * @date 2025-01-09
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService
{
    @Autowired
    private FamilyMemberMapper familyMemberMapper;

    @Autowired
    private WechatService wechatService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private DeviceDataMapper deviceDataMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private Client client;
    @Autowired
    private IDeviceDataService deviceDataService;

    @Autowired
    private AlertRuleMapper alertRuleMapper;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private FamilyMemberElderMapper familyMemberElderMapper;
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    static List<String> DEFAULT_NICKNAME_PREFIX = ListUtil.of(
            "生活更美好",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝"
    );

    /**
     * 查询老人家属
     * 
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id)
    {
        return familyMemberMapper.selectById(id);
    }

    /**
     * 查询老人家属列表
     * 
     * @param familyMember 老人家属
     * @return 老人家属
     */
    @Override
    public List<FamilyMember> selectFamilyMemberList(FamilyMember familyMember)
    {
        return familyMemberMapper.selectFamilyMemberList(familyMember);
    }

    /**
     * 新增老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int insertFamilyMember(FamilyMember familyMember)
    {
        return familyMemberMapper.insert(familyMember);
    }

    /**
     * 修改老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember)
    {
        return familyMemberMapper.updateById(familyMember);
    }

    /**
     * 批量删除老人家属
     * 
     * @param ids 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long[] ids)
    {
        return familyMemberMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除老人家属信息
     * 
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberById(Long id)
    {
        return familyMemberMapper.deleteById(id);
    }

    /**
     * 小程序登录方法
     *
     * @param userLoginRequestDto 请求数据
     * @return 登录结果，包含token和nickname
     */
    @Override
    public LoginVo login(UserLoginRequestDto userLoginRequestDto) {
        // 1.调用微信官方接口获取openId
        String openId = wechatService.getOpenId(userLoginRequestDto.getCode());

        // 2.根据openId查询数据库获取用户信息
        FamilyMember familyMember = getOne(Wrappers.<FamilyMember>lambdaQuery().eq(FamilyMember::getOpenId, openId));

        // 3.如果用户信息不存在，就创建一个用户，并绑定openId
        if (ObjectUtils.isEmpty(familyMember)) {
            // 新用户
            familyMember = new FamilyMember();
            familyMember.setOpenId(openId);
        }

        // 4.调用微信接口获取手机号
        String phoneNumber = wechatService.getPhoneNumber(userLoginRequestDto.getPhoneCode());
        // 不论是新用户还是老用户，都更新手机号
        familyMember.setPhone(phoneNumber);

        // 5.保存或更新用户，如果是新增，要生成一个用户名
        saveOrUpdateFamilyMember(familyMember);

        // 6.封装用户信息到token中，返回给小程序
        LoginVo loginVo = new LoginVo();
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", familyMember.getId());
        claims.put("nickName", familyMember.getName());

        String token = tokenService.createToken(claims);
        loginVo.setToken(token);
        loginVo.setNickName(familyMember.getName());

        // 返回结果
        return loginVo;
    }

    /**
     * 新增或更新老人家属
     * @param familyMember  老人家属对象
     */
    private void saveOrUpdateFamilyMember(FamilyMember familyMember) {
        // 判断id是否为空
        if (ObjectUtils.isEmpty(familyMember.getId())) {
            // 新增
            // 生成一个随机的用户名，规则是：一个随机的好听的名字+手机号后4位
            String prefix = DEFAULT_NICKNAME_PREFIX.get((int) (Math.random() * DEFAULT_NICKNAME_PREFIX.size()));
            String nickName = prefix + familyMember.getPhone().substring(7);
            familyMember.setName(nickName);
            familyMemberMapper.insert(familyMember);
        } else {
            // 更新
            familyMemberMapper.updateById(familyMember);
        }
    }

    /**
     * 添加家属
     *
     * @param familyDto
     */
    @Override
    public Integer addFamily(AddFamilyDto familyDto) {
        Long userId = UserThreadLocal.getUserId();
        //判断是否登录
        if (ObjectUtil.isEmpty(userId)) {
            throw new BaseException("请先登录");
        }
        //判断身份证号是否正确 判断身份证是否为空 判断姓名是否为空
        if (ObjectUtil.isEmpty(familyDto.getIdCard()) || ObjectUtil.isEmpty(familyDto.getName()) || !IdcardUtil.isValidCard(familyDto.getIdCard())) {
            throw new BaseException("身份证号格式有误或暂无老人信息");
        }


        //查询养老院中是否存在老人
        Elder elder = elderMapper.selectOne(Wrappers.<Elder>lambdaQuery()
                .eq(Elder::getIdCardNo, familyDto.getIdCard())
                .eq(Elder::getName, familyDto.getName()));
        if (ObjectUtil.isEmpty(elder)) {
            throw new BaseException("该老人未入住");
        }
        //查询该老人是否签订合同
        Contract contract = contractMapper.selectOne(Wrappers.<Contract>lambdaQuery()
                .eq(Contract::getElderId, elder.getId()));
        //判断是否有合同 如果没有签订  则提示该老人未签订合同
        if (ObjectUtil.isEmpty(contract)) {
            throw new BaseException("该老人未签订合同");
        }
        //根据老人id判断是否重复添加了家属
        Long elderId = elder.getId();
        Long count = familyMemberElderMapper.selectCount(Wrappers.<FamilyMemberElder>lambdaQuery()
                .eq(FamilyMemberElder::getElderId, elderId));
        if (count != 0) {
            throw new BaseException("该老人已添加家属,请勿重复添加");
        }


        FamilyMemberElder familyMemberElder = new FamilyMemberElder();
        familyMemberElder.setElderId(elder.getId());
        familyMemberElder.setFamilyMemberId(userId);
        familyMemberElder.setRemark(familyDto.getRemark());
        familyMemberElder.setCreateBy(String.valueOf(userId));
        familyMemberElder.setUpdateBy(String.valueOf(userId));
        int i = familyMemberElderMapper.insert(familyMemberElder);
        return i;
    }

    /**
     * 获取我的家属
     *
     * @return
     */
    @Override
    public List<FamilyMemberElderVo> getMyFamily() {


//查询出是该登录人所绑定的家属列表
        List<FamilyMemberElder> familyMemberElders = familyMemberElderMapper.selectList(Wrappers.<FamilyMemberElder>lambdaQuery()
                .eq(FamilyMemberElder::getFamilyMemberId, UserThreadLocal.getUserId()));
        FamilyMemberElderVo familyMemberElderVo = new FamilyMemberElderVo();
        List<FamilyMemberElderVo> familyMemberElderVos = new ArrayList<>();
        familyMemberElders.forEach(familyMemberElder -> {
            BeanUtils.copyProperties(familyMemberElder, familyMemberElderVo);
            familyMemberElderVo.setElderName(elderMapper.selectById(familyMemberElder.getElderId()).getName());

            familyMemberElderVos.add(familyMemberElderVo);
        });
        return familyMemberElderVos;
    }

    /**
     * 查看已绑定家人列表（分页查询)
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public List<ListByPageVo> listByPage(Integer pageNum, Integer pageSize) {

        List<ListByPageVo> list = new ArrayList<>();

        //获取绑定家属列表
        List<FamilyMemberElder> familyMemberElders = familyMemberElderMapper.selectList(Wrappers.<FamilyMemberElder>lambdaQuery()
                .eq(FamilyMemberElder::getFamilyMemberId, UserThreadLocal.getUserId()));
        familyMemberElders.forEach(familyMemberElder -> {
            //todo
            ListByPageVo listByPageVo = new ListByPageVo();
            //获取老人列表
            List<Elder> elders = elderMapper.selectList(Wrappers.<Elder>lambdaQuery()
                    .eq(Elder::getId, familyMemberElder.getElderId()));
            elders.forEach(elder -> {
                listByPageVo.setName(elder.getName());
                listByPageVo.setImage(elder.getImage());
                listByPageVo.setBedNumber(elder.getBedNumber());
                //调用方法 根据床位编号查询房间类型名称
                String typeName = selectRoomTypeByBedNumber(elder.getBedNumber());
                listByPageVo.setTypeName(typeName);
                //调用方法查询房间id
                String roomId = selectRoomIdByBedNumber(elder.getBedNumber());
                //调用方法获取烟雾报警 睡眠监测带设备信息并进行封装
                getDevice(roomId, elder, listByPageVo);
               /* Device device1 = deviceMapper.selectOne(Wrappers.<Device>lambdaQuery().eq(Device::getBindingLocation, roomId));
                if(ObjectUtil.isNotEmpty(device1)){
                    listByPageVo.setIotId(device1.getIotId());
                    listByPageVo.setDeviceName(device1.getDeviceName());
                    listByPageVo.setProductKey(device1.getProductKey());
                }

                //获取睡眠监测带设备
                Device device3 = deviceMapper.selectOne(Wrappers.<Device>lambdaQuery().eq(Device::getBindingLocation, elder.getBedId()));
                if(ObjectUtil.isNotEmpty(device3)){
                    listByPageVo.setIotId(device3.getIotId());
                    listByPageVo.setDeviceName(device3.getDeviceName());
                    listByPageVo.setProductKey(device3.getProductKey());
                }*/
                //获取智能手表设备
                Device device2 = deviceMapper.selectOne(Wrappers.<Device>lambdaQuery().eq(Device::getBindingLocation, elder.getId()));
                if (ObjectUtil.isNotEmpty(device2)) {
                    listByPageVo.setIotId(device2.getIotId());
                    listByPageVo.setDeviceName(device2.getDeviceName());
                    listByPageVo.setProductKey(device2.getProductKey());
                }

            });

            listByPageVo.setMid(String.valueOf(familyMemberElder.getId()));
            listByPageVo.setMremark(familyMemberElder.getRemark());
            listByPageVo.setElderId(String.valueOf(familyMemberElder.getElderId()));
            list.add(listByPageVo);
        });


        return list;
    }

    /**
     * 根据房间id 老人床位或房间号或者查询三种设备信息 并进行封装
     *
     * @param roomId
     * @param elder
     */
    private void getDevice(String roomId, Elder elder, ListByPageVo listByPageVo) {
        Device device = deviceMapper.selectOne(Wrappers.<Device>lambdaQuery().eq(Device::getBindingLocation, elder.getBedId()));

        if (ObjectUtil.isNotEmpty(device)) {
            listByPageVo.setIotId(device.getIotId());
            listByPageVo.setDeviceName(device.getDeviceName());
            listByPageVo.setProductKey(device.getProductKey());
        }
    }


    /**
     * 根据床位编号查询该床位所属房间id
     *
     * @param bedNumber
     * @return
     */
    private String selectRoomIdByBedNumber(String bedNumber) {
        String roomId = bedMapper.selectRoomIdByBedNumber(bedNumber);
        return roomId;
    }

    /**
     * 根据床位编号查询该床位所属房间类型名称
     *
     * @param bedNumber
     * @return
     */
    private String selectRoomTypeByBedNumber(String bedNumber) {
        String typeName = bedMapper.selectRoomTypeByBedNumber(bedNumber);
        return typeName;
    }

    /**
     * 1.4 查询健康数据
     *
     * @param request
     * @return
     */
    @Override
    public AjaxResult queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryDevicePropertyStatusResponse response;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (!response.getBody().getSuccess()) {
            throw new BaseException("调用IOT平台查询失败");
        }

        // 获取结果并返回
        return AjaxResult.success(response.getBody().getData());
    }

    /**
     * 1.5  按天统计查询指标数据
     *
     * @param iotId
     * @param functionId
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public List<DeviceDataListByDayVo> queryDeviceDataListByDay(String iotId, String functionId, Long startTime, Long endTime) {

        List<DeviceDataListByDayVo> deviceDataListByDayVos = new ArrayList<>();
        //生成24个时间
        for (int i = 0; i < 24; i++) {
            DeviceDataListByDayVo deviceDataListByDayVo = new DeviceDataListByDayVo();
            //开始时间
            long start = startTime + (i * 3600000);
            long end=start+3600000;
            //转换成localdatetime类型
            LocalDateTime startDateTime = LocalDateTimeUtil.of(start);
            LocalDateTime endDateTime = LocalDateTimeUtil.of(end);
            //判断结束时间是否在当前时间之前
            if( end>endTime ){
                break;
            }
            //如果是双位数的时间
            if(i>=10){
                deviceDataListByDayVo.setDateTime(startDateTime.toString().substring(11,16));
                //根据iotid functionId startDateTime endDateTime查询数据库获取数据
                Long resultData = deviceDataMapper.findData(iotId,functionId,startDateTime,endDateTime);
               if(ObjectUtil.isEmpty(resultData)){
                   deviceDataListByDayVo.setDataValue(0.0);
               }else{
                   deviceDataListByDayVo.setDataValue(resultData.doubleValue());
               }
                deviceDataListByDayVos.add(deviceDataListByDayVo);
            }else{
                deviceDataListByDayVo.setDateTime(startDateTime.toString().substring(11,13)+":00");
                Long resultData = deviceDataMapper.findData(iotId,functionId,startDateTime,endDateTime);

                if(ObjectUtil.isEmpty(resultData)){
                    deviceDataListByDayVo.setDataValue(0.0);
                }else{
                    deviceDataListByDayVo.setDataValue(resultData.doubleValue());
                }
                deviceDataListByDayVos.add(deviceDataListByDayVo);
            }
        }
        return deviceDataListByDayVos;
    }

//1.6 按周统计查询指标数据
    @Override
    public List<DeviceDataListByDayVo> queryDeviceDataListByWeek(String iotId, String functionId, Long startTime, Long endTime) {
        List<DeviceDataListByDayVo> deviceDataListByDayVos = new ArrayList<>();
        //生成7天
        for (int i = 0; i < 7; i++) {
            DeviceDataListByDayVo deviceDataListByDayVo = new DeviceDataListByDayVo();
            //开始时间
            long start = startTime + (i * 86400000);
            long end=start+86400000-1;
            //转换成localdatetime类型
            LocalDateTime startDateTime = LocalDateTimeUtil.of(start);
            LocalDateTime endDateTime = LocalDateTimeUtil.of(end);
            //判断结束时间是否在当前时间之前
            if( end>endTime ){
                break;
            }
            //格式化LocalDate对象为String类型
            String dateTime = startDateTime.format(DateTimeFormatter.ofPattern("MM-dd"));
            deviceDataListByDayVo.setDateTime(dateTime);
            Long resultData = deviceDataMapper.findData(iotId,functionId,startDateTime,endDateTime);
            if(ObjectUtil.isEmpty(resultData)){
                deviceDataListByDayVo.setDataValue(0.0);
            }else{
                deviceDataListByDayVo.setDataValue(resultData.doubleValue());
            }
            deviceDataListByDayVos.add(deviceDataListByDayVo);
        }
        return deviceDataListByDayVos;
    }
}
